import fs from 'fs'
import path from 'path'
import glob from 'glob'
import cli from 'cli-ux'
import { ffmpegHelper } from './ffmpegHelper'

export class BatchRepairer {
  public dirPath: string = ''
  public tasks: ITaskItem[] = []
  public curentIndex = 0
  public time = 0
  public step: Step = 'NotStarted'
  public saveJsonPath: string = ''

  public start() {
    if (this.step === 'NotStarted') {
      this.getFiles()
    } else if (this.step === 'FindEnd') {
      this.check(this.curentIndex)
    } else if (this.step === 'CheckEnd') {
      this.repair(this.curentIndex)
    } else {

    }
  }

  private getFiles() {
    console.log('get files', 'start')
    glob(`${this.dirPath}/**/*.mp4`, (error, files) => {
      if (error) {
        throw error
      } else {
        this.tasks = files.map(n => ({
          filepath: n,
          status: 'NotStarted'
        }))
        console.log('get files', 'files count', this.tasks.length)
        this.curentIndex = 0
        this.step = 'FindEnd'
        this.save()
        this.check()
      }
    })
  }

  private async check(startIndex: number = 0) {
    const bar = cli.progress({
      format: 'check [{bar}] {percentage}% | 预计剩余时间: {eta}s',
    })
    bar.start(this.tasks.length, startIndex)
    for (let i = startIndex; i < this.tasks.length; i++) {
      try {
        // const result = await ffmpegHelper.simpleCheck(this.tasks[i].filepath)
        const result = false
        this.tasks[i].status = result ? 'DoNotRepair' : 'WaitRepair'
      } catch (error) {
        console.error(error)
        this.tasks[i].status = 'CheckError'
      }
      bar.update(i + 1)
      this.curentIndex = i + 1
      this.save()
    }
    bar.stop()
    this.step = 'CheckEnd'
    this.curentIndex = 0
    this.save()
    this.repair()
  }

  private async repair(startIndex: number = 0) {
    console.log(`repair all: ${startIndex} / ${this.tasks.length}`)
    for (let i = startIndex; i < this.tasks.length; i++) {
      console.log(`repair all: ${i} / ${this.tasks.length}`)
      if (this.tasks[i].status === 'WaitRepair' || this.tasks[i].status === 'RepairError') {
        const videoSrc = this.tasks[i].filepath
        const newSrcPath = path.join(path.dirname(videoSrc), `${path.basename(videoSrc, path.extname(videoSrc))}_new${path.extname(videoSrc)}`)
        if (fs.existsSync(newSrcPath)) {
          fs.unlinkSync(newSrcPath)
        }
        const videoBar = cli.progress({
          format: 'current video [{bar}] {percentage}% | 预计剩余时间: {eta}s',
        })
        videoBar.start(100, 0)
        try {
          await ffmpegHelper.simpleRepair(videoSrc, newSrcPath, (percent) => {
            videoBar.update(Math.floor(percent))
          })
          fs.unlinkSync(videoSrc)
          fs.renameSync(newSrcPath, videoSrc)
          this.tasks[i].status = 'RepairEnd'
        } catch (error) {
          console.error(error)
          this.tasks[i].status = 'RepairError'
        }
        videoBar.stop()
      }
      this.curentIndex = i + 1
      this.save()
    }
    if (!this.tasks.find(n => n.status === 'CheckError' || n.status === 'NotStarted' || n.status === 'RepairError' || n.status === 'WaitRepair')) {
      this.step = 'End'
      console.log('修复完成')
    } else {
      this.curentIndex = 0
      console.log('修复完成, 但存在一些问题，建议查看任务文件')
    }
    this.save()
  }

  private save() {
    const json = JSON.stringify(this, null, 2)
    fs.writeFileSync(this.saveJsonPath, json, { encoding: 'utf-8' })
  }

}

type Step = 'NotStarted' | 'FindEnd' | 'CheckEnd' | 'End'

type TaskStatus = 'NotStarted' | 'WaitRepair' | 'DoNotRepair' | 'CheckError' | 'RepairError' | 'RepairEnd'

interface ITaskItem {
  filepath: string
  status: TaskStatus
}
